
#pragma once

#include <WinDef.h>

#include <DXGI.h>

struct ID3D10BlendState;
struct ID3D10Blob;
struct ID3D11Device;
struct ID3D11DeviceContext;
struct ID3D11RenderTargetView;
struct ID3D11DepthStencilView;
struct ID3D11DepthStencilState;
struct ID3D11RasterizerState;

class IndexBuffer;
class RenderTarget;
class Shader;
class Size;
class Vector4;
class VertexBuffer;

class Renderer
{
public:
	Renderer();
	~Renderer();

	// Initialization & termination.
	//----------------------------------------------
	BOOL IsValid() CONST;

	BOOL Initialize(HWND hWnd, CONST Size& resolution, DXGI_FORMAT format, ULONG mode);
	VOID Terminate();

	// State management.
	//----------------------------------------------
	VOID SetAdditiveBlending(BOOL value);

	// Buffer management.
	//----------------------------------------------
	BOOL Bind(VertexBuffer& buffer) CONST;
	VOID Unbind(VertexBuffer& buffer) CONST;
	
	BOOL Bind(IndexBuffer& buffer) CONST;
	VOID Unbind(IndexBuffer& buffer) CONST;
	
	VOID SetVertexBuffer(VertexBuffer* buffer);
	VOID SetIndexBuffer(IndexBuffer* buffer);

	VOID SetQuadBuffers();

	// Shader management.
	//----------------------------------------------
	BOOL Bind(Shader& shader) CONST;
	VOID Unbind(Shader& shader) CONST;
	
	VOID SetShader(Shader* shader);

	// Render target management.
	//----------------------------------------------
	BOOL Bind(RenderTarget& render_target);
	VOID Unbind(RenderTarget& render_target);

	VOID SetBackbuffer(BOOL enable);
	VOID SetDepthbuffer(BOOL enable);

	VOID SetRenderTargets(UINT count, RenderTarget* CONST * render_targets);

	// Clearing.
	//----------------------------------------------
	VOID ClearBackBuffer(const Vector4& color);
	VOID ClearBackBuffer(FLOAT r = 0.0f, FLOAT g = 0.0f, FLOAT b = 0.0f, FLOAT a = 1.0f);
	VOID ClearDepthBuffer();
	VOID ClearStencilBuffer();

	// Rendering.
	//----------------------------------------------
	VOID Render();
	VOID Swap();

protected:
	Renderer(CONST Renderer&);
	Renderer& operator = (CONST Renderer&);

private:
	BOOL InitializeDX11(HWND hWnd, CONST Size& resolution, DXGI_FORMAT format, ULONG mode);
	VOID TerminateDX11();

	// Attributes.
	//-----------------------------------------------
	// Direct 3D.
	ID3D11Device*			 m_device;
	ID3D11DeviceContext*	 m_context;
	
	IDXGISwapChain*			 m_swap_chain;

	ID3D11RenderTargetView*  m_render_target_view;
	ID3D11DepthStencilView*  m_depth_stencil_view;

	// States.
	ID3D11BlendState*		 m_blend_state_add;
	ID3D11BlendState*		 m_blend_state_replace;

	ID3D11DepthStencilState* m_depth_stencil_state;
	ID3D11DepthStencilState* m_depth_stencil_state_disable;

	ID3D11RasterizerState*   m_rasterizer_state;

	// Index buffers.
	IndexBuffer*             m_index_buffer;
	IndexBuffer*             m_quad_index_buffer;

	// Full screen quad data.
	VertexBuffer*			 m_vb_quad;
	IndexBuffer*		     m_ib_quad;

	FLOAT*					 m_vb_ptr;
	UINT*					 m_ib_ptr;

	// Flags.
	BOOL					 m_initialized;
};

